---
title: PdfAPI.Core architecture
summary: Architectural responsibilities, boundaries, and interaction patterns.
status: draft
owner: SAIF Doc Gen
last_reviewed: 2026-09-17
library: PdfAPI.Core
reference_type: package
---

# PdfAPI.Core architecture

PdfAPI.Core is the shared contracts-and-primitives layer of the `IT.CoreServices.PDFAPI` repository: it defines the request, result, document, page-range, and tracking types used by the `PdfAPI` Web API service, the `PdfAPI.SyncFusionCore` processor library, and the `PdfAPI.Client` package, and it ships a small, stateless set of iTextSharp-backed PDF utilities. It sits at depth 1 of the repository's reference graph — depended on by every other project in the repository, while depending on no in-repo project itself.

## Responsibilities

- Define the shared request/result/options/tracking DTOs and enums (`PdfRequest`, `ConvertRequest`, `MergeRequest`, `ExtractPagesRequest`, `PdfOptions`, `PdfResult`, `PdfTrackingInfo`, `PdfTrackingMetadata`, `DocumentTypes`, `PdfConversionType`, `PdfFormat`, `PdfProcessorType`, `PdfStatus`) that form the wire and in-process vocabulary shared by the API service, the processor library, and the client package.
- Provide the `Document`, `DocumentRange`, `DocumentRangeFactory`, and `PageRange`/`IPageRange` types that model an in-memory-or-on-disk file and the page selections made against it, including page-expression parsing (`"1-5,7,9-*,*"`).
- Provide `PdfClientService`, the only behaviour-bearing type in the library: a static, stateless facade over iTextSharp 5.5.11 offering PDF inspection ([BR-01](business-rules.md#br-01-pdf-signature-validation), [BR-08](business-rules.md#br-08-pdf-version-extraction), [BR-09](business-rules.md#br-09-page-count-via-marker-scan), [BR-10](business-rules.md#br-10-form-field-detection-requires-acroform)), transformation (`Flatten`, `ExtractPages`/`ExtractPageRanges`), and guard operations (`ValidatePdf`), all executing entirely in the caller's process with no network or database access.
- Define cache request/result contracts (`PdfAPI.Core.Cache.CacheType`, `PdfCacheRequest`, `PdfCacheCreationRequest`, `PdfCacheResult`) that describe a cache lookup/write outcome without implementing any cache store.
- Carry dormant, non-compiled source (`PdfAPI.Core.v1.*` legacy contracts and `PdfAPI.Services.PdfSettings`) that ships as source inside consumer NuGet packages but is excluded from the built assembly and unusable by binary consumers.

## Component boundaries

- **Contract layer vs. utility layer.** Request/result/options/tracking DTOs are near-anemic (properties, constructors, `ToString()`, and a handful of computed flags); `PdfClientService` is the sole component that performs behaviour, and it binds only to iTextSharp.
- **No processor engine coupling.** `PdfProcessorType` names Syncfusion, ActivePDF, and iTextSharp as a seam, but PdfAPI.Core itself only implements the iTextSharp path; the Syncfusion and ActivePDF implementations live in `PdfAPI.SyncFusionCore` and `PdfAPI\Services\ActivePdf\`, outside this library.
- **No persistence boundary crossed.** `CacheType.DbTracking`, `PdfResult.TrackingId`, and `PdfTrackingInfo` describe persistence *concepts* only; PdfAPI.Core performs no database access — those concepts are honoured by consumers.
- **File-system boundary is crossed directly.** `Document` reads, writes, and deletes files on the local/UNC file system with no abstraction or injection point; `Document.Dispose()` deletes the backing file, so a `using` block over a `Document` is destructive ([BR-24](business-rules.md#br-24-disposing-a-document-deletes-its-file)).
- **Static-facade boundary.** `PdfClientService` is entirely static, so consumers cannot substitute or mock it; the `PdfAPI` service wraps it in instance methods with a `useClient` flag to allow switching to alternative implementations.
- **Compiled vs. dormant source boundary.** Six `.cs` files (`Services\PdfSettings.cs` and the five `v1\*.cs` files) are excluded from the `<Compile>` list in `PdfAPI.Core.csproj` but are still globbed as source into both shipped NuGet packages; they are unusable by consumers of the compiled `PdfAPI.Core.dll`.

## Interaction model

- Consumers (`PdfAPI` service, `PdfAPI.Client`, `PdfAPI.SyncFusionCore`) construct a `PdfRequest`-derived request, optionally build a `DocumentRange`/`PageRange` selection over a `Document`, and call into `PdfClientService` for inspection, flattening, or extraction.
- `PdfClientService` operations guard their input through `IsPdf`/`ValidatePdf` before delegating to iTextSharp (`PdfReader`, `PdfStamper`, `PdfCopy`) and return a `PdfResult` describing the outcome.
- `Document` mediates all file-system interaction (`Load`, `Save`, `Delete`) on behalf of both the contract layer and `PdfClientService`; disposal of a `Document`, `DocumentRange`, or `PdfResult` cascades into file deletion.
- `PdfAPI` (`PdfAPI\Services\PdfService.cs`) delegates `HasFormFields`, `Flatten`, `IsPdf`, `Version`, `GetPageCount`, and both `ValidatePdf` overloads directly to `PdfClientService`; `PdfTrackingService.cs` and `ActivePdfService.cs` construct `PdfTrackingMetadata` and call `PdfClientService.ExtractPageRanges`.
- `PdfAPI.Client` (`PdfAPI.Client\PdfClient.cs`) re-exposes `PdfClientService.Version`, `GetPageCount`, `IsPdf`, `HasFormFields`, `Flatten`, and `ExtractPages` as instance methods for remote callers of the packaged client.
- `PdfAPI.SyncFusionCore` holds a project reference to `PdfAPI.Core` (per the repository reference graph) and consumes its contract types independently of `PdfClientService`.

## Architecture diagram

The following diagram shows high-level component interactions, reproduced from the Stage 1 analysis findings.

```mermaid
flowchart LR
  caller["Consumer: PdfAPI service /<br>PdfAPI.Client / PdfAPI.SyncFusionCore"]
  req["PdfRequest / ConvertRequest /<br>MergeRequest / ExtractPagesRequest"]
  dr["DocumentRange + PageRange"]
  doc[Document]
  svc[PdfClientService]
  its[iTextSharp 5.5.11]
  res[PdfResult]
  fs["Local / UNC file system"]

  caller --> req
  req --> dr
  dr --> doc
  doc <--> fs
  caller --> svc
  dr --> svc
  svc --> its
  svc --> res
  res --> caller
```

## Sequence diagram

The following diagram shows the page-extraction sequence ([OP-08](operations-processes.md)), the most representative behaviour-bearing operation in the library.

```mermaid
sequenceDiagram
	participant Caller as Consumer (PdfAPI / PdfAPI.Client)
	participant Svc as PdfClientService
	participant Doc as Document
	participant iText as iTextSharp (PdfReader/PdfCopy)
	Caller->>Svc: ExtractPages(DocumentRange)
	Svc->>Svc: IsPdf(documentRange.Document.File)
	Svc->>iText: new PdfReader(sourceBytes)
	Svc->>iText: PdfCopy over MemoryStream, AddDocument per PageRange
	iText-->>Svc: output bytes
	Svc->>Doc: Document.Load(outputBytes, "pdf")
	Doc-->>Svc: new Document (new Guid)
	Svc-->>Caller: PdfResult (Status = Succeeded, PdfProcessorType = iTextSharp)
```

## Design constraints

- No external network or database calls are made by this library; all behaviour executes in-process against caller-supplied bytes or the local/UNC file system.
- `PdfClientService` is a static facade with no dependency-injection seam, constraining consumers that need to mock or substitute PDF processing behaviour.
- File-system paths passed to `Document.Load`, `Document.Save`, and `Document.Delete` are used without canonicalisation, allow-listing, or traversal checks — path validation is the consumer's responsibility.
- Disposal semantics are destructive: disposing a `Document`, `DocumentRange`, or `PdfResult` deletes the backing file ([BR-24](business-rules.md#br-24-disposing-a-document-deletes-its-file)), so ownership and lifetime of the underlying file must be tracked carefully by callers.
- The compiled assembly excludes the `PdfAPI.Core.v1` namespace and `PdfAPI.Services.PdfSettings`, even though both are shipped as source in the packaged NuGet packages; binary consumers cannot use these types, and the `v1\DocumentRangeFactory.cs` source file would not currently compile if re-added (it calls a `Document.Load` overload that no longer exists).
- The library binds to iTextSharp 5.5.11 only; Syncfusion and ActivePDF processing are implemented by separate projects (`PdfAPI.SyncFusionCore`, `PdfAPI\Services\ActivePdf\`) outside this library's boundary.
- `PdfTrackingMetadata.Parse` reads capture group names (`importType`, `conversionType`) that do not match the regular expression's actual group names (`import`, `type`), so round-tripping through `Create` → `Parse` always loses imaging intent and conversion type ([BR-37](business-rules.md#br-37-tracking-metadata-parse-defect)) — a known defect in the current contract implementation, not an architectural choice.

## Related documentation
- [Index](index.md)
- [Overview](overview.md)
- [Dependencies](dependencies.md)
- [Operations and processes](operations-processes.md)
- [Business rules](business-rules.md)
- [Security and authorization](security-authorization.md)
- [API reference](api/index.md)

## Sources
- `PdfAPI.Core\PdfAPI.Core.csproj`
- `PdfAPI.Core\Document.cs`
- `PdfAPI.Core\Extract\DocumentRange.cs`
- `PdfAPI.Core\Extract\PageRange.cs`
- `PdfAPI.Core\Services\PdfClientService.cs`
- `PdfAPI.Core\PdfRequest.cs`
- `PdfAPI.Core\PdfResult.cs`
- `PdfAPI.Core\PdfTrackingMetadata.cs`
- `PdfAPI.Core\Cache\`
- `PdfAPI.Core\v1\*.cs`
- `PdfAPI.Core\Services\PdfSettings.cs`
- `PdfAPI\Services\PdfService.cs`
- `PdfAPI\Services\PdfTrackingService.cs`
- `PdfAPI\Services\ActivePdf\ActivePdfService.cs`
- `PdfAPI.Client\PdfClient.cs`
